package com.hei.kml;

import com.hei.kml.converter.KMLConverter;
import com.hei.kml.validator.Validator;
import com.hei.kml.converter.JSONConverter;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.Data;

import java.util.List;

/**
 * <p><code>waylines.wpml</code>示例文件如下：</p>
 * <pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
 * &lt;kml xmlns=&quot;http://www.opengis.net/kml/2.2&quot; xmlns:wpml=&quot;http://www.dji.com/wpmz/1.0.2&quot;&gt;
 *   &lt;Document&gt;
 *     &lt;!-- Step 1: Setup Mission Configuration --&gt;
 *     &lt;wpml:missionConfig&gt;
 *       &lt;wpml:flyToWaylineMode&gt;safely&lt;/wpml:flyToWaylineMode&gt;
 *       &lt;wpml:finishAction&gt;goHome&lt;/wpml:finishAction&gt;
 *       &lt;wpml:exitOnRCLost&gt;goContinue&lt;/wpml:exitOnRCLost&gt;
 *       &lt;wpml:executeRCLostAction&gt;hover&lt;/wpml:executeRCLostAction&gt;
 *       &lt;wpml:takeOffSecurityHeight&gt;20&lt;/wpml:takeOffSecurityHeight&gt;
 *       &lt;wpml:globalTransitionalSpeed&gt;10&lt;/wpml:globalTransitionalSpeed&gt;
 *       &lt;!-- Declare drone model with M30 --&gt;
 *       &lt;wpml:droneInfo&gt;
 *         &lt;wpml:droneEnumValue&gt;67&lt;/wpml:droneEnumValue&gt;
 *         &lt;wpml:droneSubEnumValue&gt;0&lt;/wpml:droneSubEnumValue&gt;
 *       &lt;/wpml:droneInfo&gt;
 *       &lt;!-- Declare drone model with M30 --&gt;
 *       &lt;wpml:payloadInfo&gt;
 *         &lt;wpml:payloadEnumValue&gt;52&lt;/wpml:payloadEnumValue&gt;
 *         &lt;wpml:payloadPositionIndex&gt;0&lt;/wpml:payloadPositionIndex&gt;
 *       &lt;/wpml:payloadInfo&gt;
 *     &lt;/wpml:missionConfig&gt;
 *
 *     &lt;!-- Step 2: Setup A Folder for Waypoint Template --&gt;
 *     &lt;Folder&gt;
 *       &lt;wpml:templateId&gt;0&lt;/wpml:templateId&gt;
 *       &lt;wpml:executeHeightMode&gt;WGS84&lt;/wpml:executeHeightMode&gt;
 *       &lt;wpml:waylineId&gt;0&lt;/wpml:waylineId&gt;
 *       &lt;wpml:autoFlightSpeed&gt;10&lt;/wpml:autoFlightSpeed&gt;
 *       &lt;Placemark&gt;
 *         &lt;Point&gt;
 *           &lt;coordinates&gt;
 *             longitude,latitude
 *           &lt;/coordinates&gt;
 *         &lt;/Point&gt;
 *         &lt;wpml:index&gt;0&lt;/wpml:index&gt;
 *         &lt;wpml:executeHeight&gt;116.57&lt;/wpml:executeHeight&gt;
 *         &lt;wpml:waypointSpeed&gt;10&lt;/wpml:waypointSpeed&gt;
 *         &lt;wpml:waypointHeadingParam&gt;
 *           &lt;wpml:waypointHeadingMode&gt;followWayline&lt;/wpml:waypointHeadingMode&gt;
 *         &lt;/wpml:waypointHeadingParam&gt;
 *         &lt;wpml:waypointTurnParam&gt;
 *           &lt;wpml:waypointTurnMode&gt;toPointAndStopWithDiscontinuityCurvature&lt;/wpml:waypointTurnMode&gt;
 *           &lt;wpml:waypointTurnDampingDist&gt;0&lt;/wpml:waypointTurnDampingDist&gt;
 *         &lt;/wpml:waypointTurnParam&gt;
 *       &lt;/Placemark&gt;
 *       &lt;Placemark&gt;
 *         &lt;Point&gt;
 *           &lt;coordinates&gt;
 *             longitude,latitude
 *           &lt;/coordinates&gt;
 *         &lt;/Point&gt;
 *         &lt;wpml:index&gt;1&lt;/wpml:index&gt;
 *         &lt;wpml:executeHeight&gt;116.57&lt;/wpml:executeHeight&gt;
 *         &lt;wpml:waypointSpeed&gt;7&lt;/wpml:waypointSpeed&gt;
 *         &lt;wpml:waypointHeadingParam&gt;
 *           &lt;wpml:waypointHeadingMode&gt;followWayline&lt;/wpml:waypointHeadingMode&gt;
 *         &lt;/wpml:waypointHeadingParam&gt;
 *         &lt;wpml:waypointTurnParam&gt;
 *           &lt;wpml:waypointTurnMode&gt;toPointAndStopWithDiscontinuityCurvature&lt;/wpml:waypointTurnMode&gt;
 *           &lt;wpml:waypointTurnDampingDist&gt;0&lt;/wpml:waypointTurnDampingDist&gt;
 *         &lt;/wpml:waypointTurnParam&gt;
 *         &lt;!-- Declare action group for waypoint 1# --&gt;
 *         &lt;wpml:actionGroup&gt;
 *           &lt;wpml:actionGroupId&gt;0&lt;/wpml:actionGroupId&gt;
 *           &lt;wpml:actionGroupStartIndex&gt;1&lt;/wpml:actionGroupStartIndex&gt;
 *           &lt;wpml:actionGroupEndIndex&gt;1&lt;/wpml:actionGroupEndIndex&gt;
 *           &lt;wpml:actionGroupMode&gt;sequence&lt;/wpml:actionGroupMode&gt;
 *           &lt;wpml:actionTrigger&gt;
 *             &lt;wpml:actionTriggerType&gt;reachPoint&lt;/wpml:actionTriggerType&gt;
 *           &lt;/wpml:actionTrigger&gt;
 *           &lt;!-- Declare the 1st action: rotate gimbal --&gt;
 *           &lt;wpml:action&gt;
 *             &lt;wpml:actionId&gt;0&lt;/wpml:actionId&gt;
 *             &lt;wpml:actionActuatorFunc&gt;gimbalRotate&lt;/wpml:actionActuatorFunc&gt;
 *             &lt;wpml:actionActuatorFuncParam&gt;
 *               &lt;wpml:gimbalRotateMode&gt;absoluteAngle&lt;/wpml:gimbalRotateMode&gt;
 *               &lt;wpml:gimbalPitchRotateEnable&gt;0&lt;/wpml:gimbalPitchRotateEnable&gt;
 *               &lt;wpml:gimbalPitchRotateAngle&gt;0&lt;/wpml:gimbalPitchRotateAngle&gt;
 *               &lt;wpml:gimbalRollRotateEnable&gt;0&lt;/wpml:gimbalRollRotateEnable&gt;
 *               &lt;wpml:gimbalRollRotateAngle&gt;0&lt;/wpml:gimbalRollRotateAngle&gt;
 *               &lt;wpml:gimbalYawRotateEnable&gt;1&lt;/wpml:gimbalYawRotateEnable&gt;
 *               &lt;wpml:gimbalYawRotateAngle&gt;30&lt;/wpml:gimbalYawRotateAngle&gt;
 *               &lt;wpml:gimbalRotateTimeEnable&gt;0&lt;/wpml:gimbalRotateTimeEnable&gt;
 *               &lt;wpml:gimbalRotateTime&gt;0&lt;/wpml:gimbalRotateTime&gt;
 *               &lt;wpml:payloadPositionIndex&gt;0&lt;/wpml:payloadPositionIndex&gt;
 *             &lt;/wpml:actionActuatorFuncParam&gt;
 *           &lt;/wpml:action&gt;
 *           &lt;!-- Declare the 2nd action: take photo --&gt;
 *           &lt;wpml:action&gt;
 *             &lt;wpml:actionId&gt;1&lt;/wpml:actionId&gt;
 *             &lt;wpml:actionActuatorFunc&gt;takePhoto&lt;/wpml:actionActuatorFunc&gt;
 *             &lt;wpml:actionActuatorFuncParam&gt;
 *               &lt;wpml:fileSuffix&gt;point1&lt;/wpml:fileSuffix&gt;
 *               &lt;wpml:payloadPositionIndex&gt;0&lt;/wpml:payloadPositionIndex&gt;
 *             &lt;/wpml:actionActuatorFuncParam&gt;
 *           &lt;/wpml:action&gt;
 *         &lt;/wpml:actionGroup&gt;
 *       &lt;/Placemark&gt;
 *     &lt;/Folder&gt;
 *
 *   &lt;/Document&gt;
 * &lt;/kml&gt;
 * </code></pre>
 * <h2>元素说明</h2>
 * <h3>任务信息（父元素：<code>&lt;wpml:missionConfig&gt;</code>）</h3>
 * <table>
 * <thead>
 * <tr>
 * <th>元素</th>
 * <th>名称</th>
 * <th>类型</th>
 * <th>单位</th>
 * <th>取值与释义</th>
 * <th>是否必需（默认值）</th>
 * <th>支持机型</th>
 * </tr>
 * </thead>
 * <tbody><tr>
 * <td>wpml:flyToWaylineMode</td>
 * <td>飞向首航点模式</td>
 * <td>枚举-string</td>
 * <td>-</td>
 * <td>safely：安全模式<br/>（M300）飞行器起飞，上升至首航点高度，再平飞至首航点。如果首航点低于起飞点，则起飞后平飞至首航点上方再下降。<br/>（M30
 * ）飞行器起飞，上升至首航点高度，再平飞至首航点。如果首航点低于“安全起飞高度”，则起飞至“安全起飞高度”后，平飞至首航点上方再下降。注意“安全起飞高度”仅在飞行器未起飞时生效。<br/><br/>pointToPoint
 * ：倾斜飞行模式<br/>（M300）飞行器起飞后，倾斜飞到首航点。<br/>（M30）飞行器起飞至“安全起飞高度”，再倾斜爬升至首航点。如果首航点高度低于“安全起飞高度”，则先平飞后下降。</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:finishAction</td>
 * <td>航线结束动作</td>
 * <td>枚举-string</td>
 * <td>-</td>
 * <td>goHome：飞行器完成航线任务后，退出航线模式并返航。<br/>noAction：飞行器完成航线任务后，退出航线模式。<br/>autoLand：飞行器完成航线任务后，退出航线模式并原地降落。<br
 * />gotoFirstWaypoint：飞行器完成航线任务后，立即飞向航线起始点，到达后退出航线模式。* 注：以上动作执行过程，若飞行器退出了航线模式且进入失控状态，则会优先执行失控动作。</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:exitOnRCLost</td>
 * <td>失控是否继续执行航线</td>
 * <td>枚举-string</td>
 * <td>-</td>
 * <td>goContinue：继续执行航线<br/>executeLostAction：退出航线，执行失控动作</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:executeRCLostAction</td>
 * <td>失控动作类型</td>
 * <td>枚举-string</td>
 * <td>-</td>
 * <td>goBack：返航。飞行器从失控位置飞向起飞点<br/>landing：降落。飞行器从失控位置原地降落<br/>hover：悬停。飞行器从失控位置悬停</td>
 * <td>无，当wpml:exitOnRCLost为executeLostAction时为必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:takeOffSecurityHeight</td>
 * <td>安全起飞高度</td>
 * <td>浮点型</td>
 * <td>m</td>
 * <td>[2, 1500] （高度模式：相对起飞点高度）<br/> * 注：飞行器起飞后，先爬升至该高度，再根据“飞向首航点模式”的设置飞至首航点。该元素仅在飞行器未起飞时生效。</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:globalTransitionalSpeed</td>
 * <td>全局航线过渡速度</td>
 * <td>浮点型</td>
 * <td>m/s</td>
 * <td>[1,15]<br/>* 注：飞行器飞往每条航线首航点的速度。航线任务中断时，飞行器从当前位置恢复至断点的速度。</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:globalRTHHeight</td>
 * <td>全局返航高度</td>
 * <td>浮点型</td>
 * <td>m</td>
 * <td>*注：飞行器返航时，先爬升至该高度，再进行返航</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:droneInfo</td>
 * <td>飞行器机型信息</td>
 * <td>-</td>
 * <td>-</td>
 * <td><em>注：请在
 * <a href="https://developer.dji.com/doc/cloud-api-tutorial/cn/api-reference/dji-wpml/common-element.html">共用元素信息</a>
 * 章节阅读详细信息</em></td>
 * <td>-</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:payloadInfo</td>
 * <td>负载机型信息</td>
 * <td>-</td>
 * <td>-</td>
 * <td><em>注：请在
 * <a href="https://developer.dji.com/doc/cloud-api-tutorial/cn/api-reference/dji-wpml/common-element.html">共用元素信息</a>
 * 章节阅读详细信息</em></td>
 * <td>-</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:autoRerouteInfo</td>
 * <td>航线绕行</td>
 * <td>-</td>
 * <td>-</td>
 * <td>-</td>
 * <td>-</td>
 * <td>M3D/M3TD</td>
 * </tr>
 * </tbody></table>
 * <h3>航线信息（父元素：<code>&lt;Folder&gt;</code>）</h3>
 * <table>
 * <thead>
 * <tr>
 * <th>元素</th>
 * <th>名称</th>
 * <th>类型</th>
 * <th>单位</th>
 * <th>取值与释义</th>
 * <th>是否必需（默认值）</th>
 * <th>支持机型</th>
 * </tr>
 * </thead>
 * <tbody><tr>
 * <td>wpml:templateId</td>
 * <td>模板ID<br/>* 注：在一个kmz文件内该ID唯一。建议从0开始单调连续递增。在template.kml和waylines.wpml文件中，将使用该id将模板与所生成的可执行航线进行关联。</td>
 * <td>整型</td>
 * <td>-</td>
 * <td>[0, 65535]</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:waylineId</td>
 * <td>航线ID<br/>* 注：在一条航线中该ID唯一。建议从0开始单调连续递增。</td>
 * <td>整型</td>
 * <td>-</td>
 * <td>[0, 65535]</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:autoFlightSpeed</td>
 * <td>全局航线飞行速度</td>
 * <td>浮点型</td>
 * <td>m/s</td>
 * <td>[1,15]<br/>* 注：此元素定义了此模板生成的整段航线中，飞行器的目标飞行速度。如果额外定义了某航点的该元素，则局部定义会覆盖全局定义。</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:executeHeightMode</td>
 * <td>执行高度模式<br/>* 注：该元素仅在waylines.wpml中使用。</td>
 * <td>枚举-string</td>
 * <td>-</td>
 * <td>WGS84：椭球高模式<br/>relativeToStartPoint：相对起飞点高度模式<br/>realTimeFollowSurface: 使用实时仿地模式，仅支持M3E/M3T/M3M</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>Placemark(Point)</td>
 * <td>航点信息（包括航点经纬度和高度等）</td>
 * <td>-</td>
 * <td>-</td>
 * <td>请阅读文档内容，航线文件格式 &gt; template.kml 说明 &gt; Placemark</td>
 * <td>-</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:startActionGroup</td>
 * <td>航线初始动作<br/>*注：该元素用于规划一系列初始动作，在航线开始前执行。航线中断恢复时，先执行初始动作，再执行航点动作</td>
 * <td>-</td>
 * <td>-</td>
 * <td>拓展阅读：
 * <a href="https://developer.dji.com/doc/cloud-api-tutorial/cn/api-reference/dji-wpml/common-element.html">共用元素信息</a>
 * 中的 <code>&lt;wpml:actionGroup&gt;</code></td>
 * <td>-</td>
 * <td>M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * </tbody></table>
 * <h3>航点信息（<code>&lt;Placemark&gt;</code>）</h3>
 * <table>
 * <thead>
 * <tr>
 * <th>元素</th>
 * <th>名称</th>
 * <th>类型</th>
 * <th>单位</th>
 * <th>取值与释义</th>
 * <th>是否必需（默认值）</th>
 * <th>支持机型</th>
 * </tr>
 * </thead>
 * <tbody><tr>
 * <td>wpml:isRisky</td>
 * <td>是否危险点</td>
 * <td>布尔型</td>
 * <td>-</td>
 * <td>0：正常点，1：危险点</td>
 * <td>-</td>
 * <td>M30/M30T，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>Point</td>
 * <td>航点经纬度&lt;经度,纬度&gt;<br/>* 注：此处格式如“<code>&lt;Point&gt; &lt;coordinates&gt; 经度,纬度 &lt;/coordinates&gt; &lt;
 * /Point&gt;</code>”</td>
 * <td>浮点型</td>
 * <td>°,°</td>
 * <td>[-180,180],[-90,90]</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:index</td>
 * <td>航点序号<br/>* 注：在一条航线内该ID唯一。该序号必须从0开始单调连续递增。</td>
 * <td>整型</td>
 * <td>-</td>
 * <td>[0, 65535]</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:executeHeight</td>
 * <td>航点执行高度<br/>* 注：该元素仅在waylines.wpml中使用。具体高程参考平面在“wpml:executeHeightMode”中声明。</td>
 * <td>浮点型</td>
 * <td>m</td>
 * <td>-</td>
 * <td>必需元素</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:waypointSpeed</td>
 * <td>航点飞行速度，当前航点飞向下一个航点的速度</td>
 * <td>浮点型</td>
 * <td>m/s</td>
 * <td>[1, 15]</td>
 * <td>必需元素<br/>* 注：当且仅当“wpml:useGlobalSpeed”为“0”时必需</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:waypointHeadingParam</td>
 * <td>偏航角模式参数</td>
 * <td>-</td>
 * <td>-</td>
 * <td>-</td>
 * <td>必需元素<br/>* 注：当且仅当“wpml:useGlobalHeadingParam”为“0”时必需</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:waypointTurnParam</td>
 * <td>航点类型（航点转弯模式）</td>
 * <td>-</td>
 * <td>-</td>
 * <td>-</td>
 * <td>必需元素<br/>* 注：当且仅当“wpml:useGlobalTurnParam”为“0”时必需</td>
 * <td>M300 RTK，M350 RTK，M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * <tr>
 * <td>wpml:useStraightLine</td>
 * <td>该航段是否贴合直线</td>
 * <td>布尔型</td>
 * <td>-</td>
 * <td>0：航段轨迹全程为曲线<br/>1：航段轨迹尽量贴合两点连线</td>
 * <td>必需元素<br/>* 注：当且仅当“wpml:waypointTurnParam”内&quot;waypointTurnMode&quot;
 * 被设置为“toPointAndStopWithContinuityCurvature”或“toPointAndPassWithContinuityCurvature”时必需。如果此元素被设置，则局部定义会覆盖全局定义。</td>
 * <td>M30/M30T，M3E/M3T/M3M，M3D/M3TD</td>
 * </tr>
 * </tbody></table>
 */
@Data
@XStreamAlias("kml")
public class Waylines implements KMLConverter<Waylines>, JSONConverter<Waylines>, Validator {

	@XStreamAlias("Document")
	private Document document;

	@Data
	@XStreamAlias("Document")
	public static class Document {
		@XStreamAlias("wpml:missionConfig")
		private MissionConfig missionConfig;

		@XStreamAlias("Folder")
		private Folder folder;
	}

	@Data
	@XStreamAlias("wpml:missionConfig")
	public static class MissionConfig {
		@XStreamAlias("wpml:flyToWaylineMode")
		private String flyToWaylineMode;

		@XStreamAlias("wpml:finishAction")
		private String finishAction;

		@XStreamAlias("wpml:exitOnRCLost")
		private String exitOnRCLost;

		@XStreamAlias("wpml:executeRCLostAction")
		private String executeRCLostAction;

		@XStreamAlias("wpml:takeOffSecurityHeight")
		private Integer takeOffSecurityHeight;

		@XStreamAlias("wpml:globalTransitionalSpeed")
		private Integer globalTransitionalSpeed;

		@XStreamAlias("wpml:globalRTHHeight")
		private Integer globalRTHHeight;

		@XStreamAlias("wpml:droneInfo")
		private Common.DroneInfo droneInfo;

		@XStreamAlias("wpml:payloadInfo")
		private Common.PayloadInfo payloadInfo;

		@XStreamAlias("wpml:autoRerouteInfo")
		private Common.AutoRerouteInfo autoRerouteInfo;
	}

	@Data
	@XStreamAlias("Folder")
	public static class Folder {
		@XStreamAlias("wpml:templateId")
		private Integer templateId;

		@XStreamAlias("wpml:waylineId")
		private Integer waylineId;

		@XStreamAlias("wpml:executeHeightMode")
		private String executeHeightMode;

		@XStreamAlias("wpml:autoFlightSpeed")
		private Integer autoFlightSpeed;

		@XStreamAlias("wpml:startActionGroup")
		@XStreamImplicit(itemFieldName = "wpml:actionGroup")
		private List<Common.ActionGroup> startActionGroup;

		@XStreamAlias("Placemark")
		@XStreamImplicit(itemFieldName = "Placemark")
		private List<Placemark> placemark;
	}

	@Data
	@XStreamAlias("Placemark")
	public static class Placemark {
		@XStreamAlias("wpml:isRisky")
		private Integer isRisky;

		@XStreamAlias("Point")
		private Point point;

		@XStreamAlias("wpml:index")
		private Integer index;

		@XStreamAlias("wpml:executeHeight")
		private Double executeHeight;

		@XStreamAlias("wpml:waypointSpeed")
		private Integer waypointSpeed;

		@XStreamAlias("wpml:useStraightLine")
		private Integer useStraightLine;

		@XStreamAlias("wpml:waypointHeadingParam")
		private Common.WaypointHeadingParam waypointHeadingParam;

		@XStreamAlias("wpml:waypointTurnParam")
		private Common.WaypointTurnParam waypointTurnParam;

		@XStreamAlias("wpml:actionGroup")
		private Common.ActionGroup actionGroup;
	}

	@Data
	@XStreamAlias("Point")
	public static class Point {
		@XStreamAlias("coordinates")
		private String coordinates; // longitude,latitude
	}

	public void validate() {
		assert0(notBlank(document.missionConfig.flyToWaylineMode) && inSet(document.missionConfig.flyToWaylineMode, new String[]{"safely", "pointToPoint"}));
		assert0(notBlank(document.missionConfig.finishAction) && inSet(document.missionConfig.finishAction, new String[]{"goHome", "noAction", "autoLand", "gotoFirstWaypoint"}));
		assert0(notBlank(document.missionConfig.exitOnRCLost) && inSet(document.missionConfig.exitOnRCLost, new String[]{"goContinue", "executeLostAction"}));
		assert0(notBlank(document.missionConfig.executeRCLostAction) && inSet(document.missionConfig.executeRCLostAction, new String[]{"goBack", "landing", "hover"}));
		assert0(notBlank(document.missionConfig.takeOffSecurityHeight) && inScope(document.missionConfig.takeOffSecurityHeight, 2, 1500));
		assert0(notBlank(document.missionConfig.globalTransitionalSpeed) && inScope(document.missionConfig.globalTransitionalSpeed, 2, 15));
		assert0(inScope(document.missionConfig.globalRTHHeight, 2, 1500));
		if (document.missionConfig.droneInfo != null){
			Common.DroneInfo droneInfo = document.missionConfig.droneInfo;
			assert0(notBlank(droneInfo.getDroneEnumValue()) && inSet(droneInfo.getDroneEnumValue(), new String[]{"89","60","67","77","91"}));
			if (droneInfo.getDroneEnumValue().equals(67)){
				assert0(notBlank(droneInfo.getDroneSubEnumValue())&&inSet(droneInfo.getDroneSubEnumValue(), new String[]{"0","1"}));
			}
			if (droneInfo.getDroneEnumValue().equals(77)){
				assert0(notBlank(droneInfo.getDroneSubEnumValue())&&inSet(droneInfo.getDroneSubEnumValue(), new String[]{"0","1","2"}));
			}
			if (droneInfo.getDroneEnumValue().equals(91)){
				assert0(notBlank(droneInfo.getDroneSubEnumValue())&&inSet(droneInfo.getDroneSubEnumValue(), new String[]{"0","1"}));
			}
		}
		if (document.missionConfig.payloadInfo != null){
			Common.PayloadInfo payloadInfo = document.missionConfig.payloadInfo;
			assert0(notBlank(payloadInfo.getPayloadEnumValue()) && inSet(payloadInfo.getPayloadEnumValue(), new String[]{"42","43","52","53","61","66","67","68","80","81","65534","82","83"}));
			assert0(notBlank(payloadInfo.getPayloadPositionIndex()) && inSet(payloadInfo.getPayloadPositionIndex(), new String[]{"0", "2"}));
		}
		if (document.missionConfig.autoRerouteInfo != null){
			Common.AutoRerouteInfo autoRerouteInfo = document.missionConfig.autoRerouteInfo;
			assert0(notBlank(autoRerouteInfo.getMissionAutoRerouteMode()) && inSet(autoRerouteInfo.getMissionAutoRerouteMode(), new String[]{"0", "1"}));
			assert0(notBlank(autoRerouteInfo.getTransitionalAutoRerouteMode()) && inSet(autoRerouteInfo.getTransitionalAutoRerouteMode(), new String[]{"0", "1"}));
		}
		assert0(notBlank(document.folder.templateId) && inScope(document.folder.templateId, 0, 65535));
		assert0(notBlank(document.folder.waylineId) && inScope(document.folder.waylineId, 0, 65535));
		assert0(notBlank(document.folder.executeHeightMode) && inSet(document.folder.executeHeightMode, new String[]{"WGS84", "relativeToStartPoint", "realTimeFollowSurface"}));
		assert0(notBlank(document.folder.autoFlightSpeed) && inScope(document.folder.autoFlightSpeed, 1, 15));
		if (document.folder.placemark != null){
			for (Placemark placemark : document.folder.placemark) {
				assert0(notBlank(placemark.getIndex())&&inScope(placemark.getIndex(), 0, 65535));
				assert0(notBlank(placemark.getWaypointSpeed())&&inScope(placemark.getWaypointSpeed(), 1, 15));
				assert0(notBlank(placemark.getExecuteHeight()));
				assert0(inSet(placemark.getIsRisky(), new String[]{"0", "1"}));
				assert0(inSet(placemark.getUseStraightLine(), new String[]{"0", "1"}));
				assert0(notBlank(placemark.getPoint().getCoordinates())&&inScope(placemark.getPoint().getCoordinates().split(",").length, 2, 2));
				if (placemark.getWaypointTurnParam()!=null){
					Common.WaypointTurnParam waypointTurnParam = placemark.getWaypointTurnParam();
					// assert0();
				}
			}
		}
		if (document.folder.startActionGroup != null){
			for (Common.ActionGroup actionGroup : document.folder.startActionGroup) {
				assert0(notBlank(actionGroup.getActionGroupId())&&inScope(actionGroup.getActionGroupId(), 0, 65535));
				assert0(notBlank(actionGroup.getActionGroupMode())&&inSet(actionGroup.getActionGroupMode(), new String[]{"sequence"}));
				assert0(notBlank(actionGroup.getActionGroupStartIndex())&&inScope(actionGroup.getActionGroupStartIndex(), 0, 65535));
				assert0(notBlank(actionGroup.getActionGroupEndIndex())&&inScope(actionGroup.getActionGroupEndIndex(), 0, 65535)&&actionGroup.getActionGroupStartIndex() <= actionGroup.getActionGroupEndIndex());
			}
		}
	}
}
